package com.zhhtech.zhh.ui.base

import android.app.Service
import android.content.Context
import android.graphics.Canvas
import android.os.Vibrator
import android.view.View
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import com.zhhtech.zhh.ui.R
import com.zhhtech.zhh.ui.ext.toColor
import java.util.*

abstract class BaseDragSwipeRecyclerAdapter<VB : ViewBinding, B>(datas: MutableList<B> = mutableListOf()) :
    BaseRecyclerAdapter<VB, B>(datas) {

    var dragEndListener: (() -> Unit)? = null
    val mItemTouchHelper: ItemTouchHelper
    val dragSwipe: ItemTouchHelper.Callback

    protected var minDragPosition = -1

    init {
        dragSwipe = object : ItemTouchHelper.Callback() {

            override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
                return this@BaseDragSwipeRecyclerAdapter.getMovementFlags(recyclerView, viewHolder)
            }

            override fun onMove(
                recyclerView: RecyclerView,
                viewHolder: RecyclerView.ViewHolder,
                target: RecyclerView.ViewHolder,
            ): Boolean {
                return this@BaseDragSwipeRecyclerAdapter.onMove(recyclerView, viewHolder, target)
            }

            override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                this@BaseDragSwipeRecyclerAdapter.onSwiped(viewHolder, direction)
            }

            override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
                this@BaseDragSwipeRecyclerAdapter.onSelectedChanged(viewHolder, actionState)
                super.onSelectedChanged(viewHolder, actionState)
            }

            override fun isLongPressDragEnabled(): Boolean {
                return this@BaseDragSwipeRecyclerAdapter.isLongPressDragEnabled()
            }

            override fun isItemViewSwipeEnabled(): Boolean {
                return false
            }

            override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
                super.clearView(recyclerView, viewHolder)
                this@BaseDragSwipeRecyclerAdapter.clearView(recyclerView, viewHolder)
            }

            override fun onChildDraw(
                c: Canvas,
                recyclerView: RecyclerView,
                viewHolder: RecyclerView.ViewHolder,
                dX: Float,
                dY: Float,
                actionState: Int,
                isCurrentlyActive: Boolean,
            ) {
                var dY = dY
                val topY = viewHolder.itemView.top + dY
                val bottomY = topY + viewHolder.itemView.height
                if (topY < 0) {
                    dY = 0f
                } else if (bottomY > recyclerView.height) {
                    dY = (recyclerView.height - viewHolder.itemView.height - viewHolder.itemView.top).toFloat()
                }
                super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
            }
        }
        mItemTouchHelper = ItemTouchHelper(dragSwipe)
    }

    open fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
        return if (recyclerView.layoutManager is GridLayoutManager) {
            val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN or
                    ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
            val swipeFlags = 0
            ItemTouchHelper.Callback.makeMovementFlags(dragFlags, swipeFlags)
        } else {
            val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
            val swipeFlags = ItemTouchHelper.START or ItemTouchHelper.END
            ItemTouchHelper.Callback.makeMovementFlags(dragFlags, swipeFlags)
        }
    }

    open fun onMove(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder,
    ): Boolean {
        val fromPosition = viewHolder.absoluteAdapterPosition
        val toPosition = target.absoluteAdapterPosition
        if (fromPosition < toPosition) {
            for (i in fromPosition until toPosition) {
                Collections.swap(datas, i, i + 1)
            }
        } else {
            for (i in fromPosition downTo toPosition + 1) {
                Collections.swap(datas, i, i - 1)
            }
        }
        var min = fromPosition.coerceAtMost(toPosition)
        if (minDragPosition != -1) {
            min = minDragPosition.coerceAtMost(min)
        }
        minDragPosition = min
        notifyItemMoved(fromPosition, toPosition)
        return true
    }

    open fun isLongPressDragEnabled(): Boolean {
        return false
    }

    open fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        val adapterPosition = viewHolder.absoluteAdapterPosition
        datas.removeAt(adapterPosition)
        notifyItemRemoved(adapterPosition)
        notifyItemRangeChanged(adapterPosition, itemCount)
    }

    open fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
            viewHolder?.itemView?.setBackgroundColor(R.color.main_bg.toColor())
        }
    }

    open fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
        viewHolder.itemView.setBackgroundColor(R.color.white.toColor())
        if (minDragPosition != -1) {
            notifyItemRangeChanged(minDragPosition, itemCount - minDragPosition)
        }
        dragEndListener?.invoke()
    }

    override fun onBindViewHolder(holder: BaseViewHolder<VB>, position: Int) {
        super.onBindViewHolder(holder, position)
        bindDragView(holder, holder.vb.root)
    }

    fun bindDragView(holder: RecyclerView.ViewHolder, vararg views: View) {
        views.forEach { view ->
            view.setOnLongClickListener {
                vibrate(it.context, 100L)
                mItemTouchHelper.startDrag(holder)
                return@setOnLongClickListener true
            }
        }
    }

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        mItemTouchHelper.attachToRecyclerView(recyclerView)
    }

    private fun vibrate(context: Context, milliseconds: Long) {
        (context.getSystemService(Service.VIBRATOR_SERVICE) as? Vibrator)?.vibrate(milliseconds)
    }
}